#!/usr/bin/env bash

function cctl()
{
    #local color=$1
    #local other=$2
    case $1 in
        r) printf "\033[$231m";; # frontcolor red
        g) printf "\033[$232m";; # frontcolor green
        y) printf "\033[$233m";; # frontcolor yellow
        b) printf "\033[$234m";; # frontcolor blue
        p) printf "\033[$235m";; # frontcolor pink
        c) printf "\033[$236m";; # frontcolor cyan
        d) printf "\033[$237m";; # frontcolor drak white = grey
        w) printf "\033[$238m";; # frontcolor white
        0) printf "\033[$20m";;  # frontcolor reset
        bgr) printf "\033[$231m";; # background_color red
        bgg) printf "\033[$232m";; # background_color green
        bgy) printf "\033[$233m";; # background_color yellow
        bgb) printf "\033[$234m";; # background_color blue
        bgp) printf "\033[$235m";; # background_color pink
        bgc) printf "\033[$236m";; # background_color cyan
        bgd) printf "\033[$237m";; # background_color drak white = grey
        bgw) printf "\033[$238m";; # background_color white
        bg0) printf "\033[$20m";;  # background_color reset
        fg*)
            local r=$(printf "%d" "0x${1:2:2}")
            local g=$(printf "%d" "0x${1:4:2}")
            local b=$(printf "%d" "0x${1:6:2}")
            printf "\033[$238;2;$r;$g;${b}m"
            ;;
        bg*)
            local r=$(printf "%d" "0x${1:2:2}")
            local g=$(printf "%d" "0x${1:4:2}")
            local b=$(printf "%d" "0x${1:6:2}")
            printf "\033[$248;2;$r;$g;${b}m"
            ;;
        *)
            if [ ${#1} = 6 ]; then
                local r=$(printf "%d" "0x${1:0:2}")
                local g=$(printf "%d" "0x${1:2:2}")
                local b=$(printf "%d" "0x${1:4:2}")
                printf "\033[$238;2;$r;$g;${b}m"
            fi
            ;;
    esac
}

LOG_DEPTH=0
function log_depth_inc()
{
    (( LOG_DEPTH++ ))
}

function log_depth_dec()
{
    (( LOG_DEPTH-- ))
}

LOG_DEBUG=${LOG_DEBUG:-false}
function logd()
{
    $LOG_DEBUG && printf "%s:%3d " ${BASH_SOURCE[$((1 + LOG_DEPTH))]} ${BASH_LINENO[$LOG_DEPTH]}
    echo -en "$(cctl c)$*$(cctl 0)\n"
}

function logi()
{
    $LOG_DEBUG && printf "%s:%3d " ${BASH_SOURCE[$((1 + LOG_DEPTH))]} ${BASH_LINENO[$LOG_DEPTH]}
    echo -en "$(cctl g)$*$(cctl 0)\n"
}

function logw()
{
    $LOG_DEBUG && printf "%s:%3d " ${BASH_SOURCE[$((1 + LOG_DEPTH))]} ${BASH_LINENO[$LOG_DEPTH]}
    echo -en "$(cctl y)$*$(cctl 0)\n"
}

function loge()
{
    $LOG_DEBUG && printf "%s:%3d " ${BASH_SOURCE[$((1 + LOG_DEPTH))]} ${BASH_LINENO[$LOG_DEPTH]}
    echo -en "$(cctl r)$*$(cctl 0)\n"
}

function print_code()
{
    local source_id="$1"
    local source_file="$2"
    local source_line="$3"
    local source_range="${4:-5}"
    local source_range_start="$(( source_line - source_range ))"
    local source_range_end="$(( source_line + source_range ))"
    source_range_start="$((source_range_start >= 1 ? source_range_start : 1))"

    printf "* $(cctl c)$source_id $(cctl g)$source_file $(cctl r)$source_line$(cctl 0)\n"
    cat -n "$source_file" |
        sed -n "$source_range_start,${source_range_end}p" |
        sed "s/^\(\s*[0-9]*\)\t/$(cctl y)*\1|$(cctl 0) /g" |
        sed "s/\t/$(cctl 777777)\\\\t->->->$(cctl 0)/g" |
        sed "s/\*\(\s*$source_line|\)/$(cctl bg444444)>\1$(cctl 0)/g"
}

function print_source()
{
    sed "s/^ \{$1\}//" <<< "${!2}"
}

function dumpstack()
{
    local i j
    for (( i = 0, j = 1; j < ${#BASH_SOURCE[*]}; i++, j++ )); do
        print_code "$j" "$(realpath ${BASH_SOURCE[$j]})" "${BASH_LINENO[$i]}"
    done
}

function report()
{
    local action="$1"; shift
    logd "开始${action}"
    if "$@"; then
        logi "${action}成功"
    else
        logd "${action}失败"
        return 1
    fi
    return
}

function report_cmd()
{
    local action="$*"
    logd "开始${action}"
    if "$@"; then
        logi "${action}成功"
    else
        logd "${action}失败"
        return 1
    fi
    return
}

declare flog_filename="$HOME/log/shell/default.log"
function set_flog_file()
{
    flog_filename="$1"
}

function flog()
{
    $* | tee -a $flog_filename
}

function flogd()
{
    local fmt="$1"; shift
    printf "$(date +%Y.%m.%d\ %H:%M:%S) ${BASH_SOURCE[1]}:${BASH_LINENO[0]} $(cctl c)$fmt$(cctl 0)\n" $* | tee -a $flog_filename
}

function flogi()
{
    local fmt="$1"; shift
    printf "$(date +%Y.%m.%d\ %H:%M:%S) ${BASH_SOURCE[1]}:${BASH_LINENO[0]} $(cctl g)$fmt$(cctl 0)\n" $* | tee -a $flog_filename
}

function flogw()
{
    local fmt="$1"; shift
    printf "$(date +%Y.%m.%d\ %H:%M:%S) ${BASH_SOURCE[1]}:${BASH_LINENO[0]} $(cctl y)$fmt$(cctl 0)\n" $* | tee -a $flog_filename
}

function floge()
{
    local fmt="$1"; shift
    printf "$(date +%Y.%m.%d\ %H:%M:%S) ${BASH_SOURCE[1]}:${BASH_LINENO[0]} $(cctl r)$fmt$(cctl 0)\n" $* | tee -a $flog_filename
}
